using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Microsoft.PowerShell.CmdletManagement.CompareCmdlet
{
    public class NonameParameterSet
    {
        private int _parameterSetId;
        private List<PsSpecCmdletParameterData> _parameters = new List<PsSpecCmdletParameterData>();
        private CmdletInfo _cmdletInfo;
        List<IMismatch> _mismatches = new List<IMismatch>();

        public NonameParameterSet() {
            _parameterSetId = 0;
        }

        public NonameParameterSet(int parameterSetId) {
            _parameterSetId = parameterSetId;
        }

        public virtual string Name {
            get {return "No name";}
        }

        public void AddParameter(PsSpecCmdletParameterData parameter) {
            _parameters.Add(parameter);
            parameter.ParameterSet = this;
        }

 
        public void RemoveParameter(PsSpecCmdletParameterData parameter)
        {
            _parameters.Remove(parameter);
        }

        /// <summary>
        /// Finds the parameter metadata for the parameter with the specified name and returns it in the out parameter.
        /// If the parameter is found, the method will return true, otherwise false.
        /// </summary>
        /// <param name="name">The name of the parameter to find.</param>
        /// <param name="parameter">The parameter which was found, else null.</param>
        /// <returns>True, if a parameter is found matching the specified name.</returns>
        public bool TryGetParameter(string name, out PsSpecCmdletParameterData parameter)
        {
            parameter = _parameters.Find(
                delegate(PsSpecCmdletParameterData parameterData)
                {
                    return parameterData.Name.Equals(name);
                }
            );

            return parameter != null;
        }

        public List<PsSpecCmdletParameterData> Parameters {
            get {return _parameters;}
        }

        public void CompareToImplementation(NonameParameterSet implementedParameterSet) {
            List<PsSpecCmdletParameterData> implementedParameters = implementedParameterSet.Parameters;
            IMismatch mismatch;
            if(_parameters.Count != implementedParameters.Count) {
                mismatch = new ParameterSetMismatch(this,
                    String.Format("Specified [{0}] parameters but implemented [{1}] parameters.", _parameters.Count, implementedParameters.Count));
                _mismatches.Add(mismatch);
            }
            _mismatches.AddRange(implementedParameterSet.VerifySpecsParameterList(_parameters));
        }

        public List<IMismatch> VerifySpecsParameterList(List<PsSpecCmdletParameterData> specifiedParameterList) {
            List<IMismatch> mismatches = new List<IMismatch>();
            List<PsSpecCmdletParameterData> implementedParameterList = new List<PsSpecCmdletParameterData>(_parameters);
            foreach(PsSpecCmdletParameterData specifiedParameter in specifiedParameterList) {
                bool parameterFound = false;
                foreach(PsSpecCmdletParameterData implementedParameter in implementedParameterList) {
                    if(implementedParameter.HasName(specifiedParameter)) {
                        // The specified parameter found, check fields
                        parameterFound = true;
                        specifiedParameter.CompareToImplementation(implementedParameter);
                        // Weed out the implemented parameter that has been compared to specification already
                        implementedParameterList.Remove(implementedParameter);
                        break;
                    }
                }
                if(!parameterFound) {
                    // The parameter was not found
                    IMismatch mismatch = new ParameterSetMismatch(this,
                        String.Format("Specified parameter [{0}] is not implemented.", specifiedParameter.Name));
                    mismatches.Add(mismatch);
                }
            }
            // Check if all implemented parameters have been specified
            if(implementedParameterList.Count > 0) {
                // There are implemented parameters that have not been specified
                foreach(PsSpecCmdletParameterData implementedParameter in implementedParameterList) {
                    IMismatch mismatch = new ParameterSetMismatch(this,
                        String.Format("Implemented parameter [{0}] is not specified.", implementedParameter.Name));
                    mismatches.Add(mismatch);
                }
            }
            return mismatches;
       }

        public CmdletInfo CmdletInfo {
            get {return _cmdletInfo;}
            set {_cmdletInfo = value;}
        }

        ///<summary>Returns a total number of errors in this cmdlet</summary>
		public int CountMismatches(int counter) {
            foreach(PsSpecCmdletParameterData parameter in _parameters) {
                counter = parameter.CountMismatches(counter);
            }
            foreach(IMismatch mismatch in _mismatches) {
                counter = mismatch.CountMismatches(counter);
            }
			return counter;
		}

        public void AddMismatchesToList(List<IMismatch> store) {
            store.AddRange(_mismatches);
            foreach(PsSpecCmdletParameterData parameter in _parameters)
                parameter.AddMismatchesToList(store);
        }

        public void SortMismatches(List<IMismatch> highList, List<IMismatch> warningList) {
            // Sort parameter set level mismatches
            foreach(IMismatch mismatch in _mismatches) {
                mismatch.AddMismatch(highList);
                mismatch.AddMismatch(warningList);
            }
            // Sort mismatches on the level of parameters
			foreach(PsSpecCmdletParameterData parameter in _parameters) {
                parameter.SortMismatches(highList, warningList);
            }
        }
    }
}
